package org.korosoft.rusalad.syncnrun;

import org.apache.commons.cli.ParseException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.korosoft.rusalad.syncnrun.cli.*;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * Syncnrun entry point class.
 *
 * @author Dmitry Korotkov
 * @since 1.0
 */
public class Main {

    private static final Log log = LogFactory.getLog(Server.class);

    public static final int DEFAULT_PORT = 5901;
    public static final int DEFAULT_RETRIES = 1;

    public static final Map<String, CliCommand> commands = new HashMap<String, CliCommand>();
    public static final String DEFAULT_HOST = "localhost";

    private static CliCommand addCommand(Class<? extends CliCommand> clazz) {
        final CliCommand command;
        try {
            command = clazz.newInstance();
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        if (commands.containsKey(command.getName())) {
            throw new IllegalStateException(String.format("Command with name %s is already registered", command.getName()));
        }
        commands.put(command.getName(), command);
        return command;
    }

    public static void main(String[] args) throws IOException, ParseException, InterruptedException {

        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                log.debug(e.getMessage(), e);
                log.error(e.getMessage());
            }
        });

        CliCommand help = addCommand(CliHelp.class);
        addCommand(CliServer.class);
        addCommand(CliPing.class);
        addCommand(CliExec.class);
        addCommand(CliSend.class);
        addCommand(CliRetrieve.class);
        addCommand(CliVersion.class);

        if (args.length == 0) {
            help.execute(args);
            return;
        }

        final String commandName = args[0];
        if (args.length == 1) {
            args = new String[0];
        } else {
            args = Arrays.copyOfRange(args, 1, args.length);
        }
        final CliCommand command = commands.get(commandName);
        if (command == null) {
            System.err.printf("Unknown command: %s%n", commandName);
            help.execute(args);
        } else {
            command.execute(args);
        }
    }
}
